package com.join.template.core.grammar.generate;

import com.join.template.core.configuration.ExpressionConfig;
import com.join.template.core.configuration.JoinConfig;
import com.join.template.core.constant.Constant;
import com.join.template.core.constant.EntityType;
import com.join.template.core.constant.MarkedWords;
import com.join.template.core.factory.JoinFactory;
import com.join.template.core.grammar.config.GenerateConfig;
import com.join.template.core.grammar.handle.Grammar;
import com.join.template.core.grammar.info.GrammarInfo;
import com.join.template.core.listener.GenerateListener;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author CAOYOU
 * @Title: AGenerateGrammar
 * @date 2019/10/2110:54
 */
public abstract class AbstractGenerateGrammar<P, C> implements Generate<P, C> {

    protected JoinFactory joinFactory;

    protected ExpressionConfig expression;

    protected GenerateListener generateListener;

    protected GenerateConfig generateConfig;

    protected Class<? extends GrammarInfo> grammarInfoClass;

    protected List<GrammarInfo> grammarInfos;

    public AbstractGenerateGrammar(JoinFactory joinFactory) {
        this.joinFactory = joinFactory;
        this.expression = joinFactory.getConfiguration().getExpression();
        this.grammarInfos = new ArrayList<>();
    }

    @Override
    public Generate setGenerateListener(GenerateListener generateListener) {
        this.generateListener = generateListener;
        return this;
    }

    @Override
    public Generate setGenerateConfig(GenerateConfig generateConfig) {
        this.generateConfig = generateConfig;
        return this;
    }

    @Override
    public Generate setGrammarInfoClass(Class<? extends GrammarInfo> grammarInfoClass) {
        this.grammarInfoClass = grammarInfoClass;
        return this;
    }

    @Override
    public List<? extends GrammarInfo> getGrammarInfos() {
        return grammarInfos;
    }

    protected void createGrammarIndex(GrammarInfo current) throws IllegalAccessException, InstantiationException {
        GrammarInfo index = this.grammarInfoClass.newInstance();
        index.setParentName(current.getName());
        index.setParentType(current.getType());
        index.setName(current.getName().concat("_").concat(expression.getAttIndex()));
        index.setType(EntityType.Integer);
        index.setDescribe(MarkedWords.getAttrIndexName());
        index.setGrammarType(Constant.EXPR_VAR);

        Grammar grammar = joinFactory.getGrammar(index.getGrammarType());

        Map<String, Object> root = new HashMap<>();
        root.put(this.generateConfig.getNameKey(), index.getName());
        root.put(this.generateConfig.getTypeKey(), EntityType.Integer.name());
        String example = grammar.getExample().genExample(index);
        index.setGrammar(example);

        current.addChild(index);
    }
}
